package com.guojiang.guopicturebackend.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guojiang.guopicturebackend.exception.ErrorCode;
import com.guojiang.guopicturebackend.exception.ThrowUtils;
import com.guojiang.guopicturebackend.model.dto.spaceuser.SpaceUserAddRequest;
import com.guojiang.guopicturebackend.model.dto.spaceuser.SpaceUserQueryRequest;
import com.guojiang.guopicturebackend.model.entity.Space;
import com.guojiang.guopicturebackend.model.entity.SpaceUser;
import com.guojiang.guopicturebackend.model.entity.User;
import com.guojiang.guopicturebackend.model.enums.SpaceLevelEnum;
import com.guojiang.guopicturebackend.model.enums.SpaceRoleEnum;
import com.guojiang.guopicturebackend.model.enums.SpaceTypeEnum;
import com.guojiang.guopicturebackend.model.vo.space.SpaceVO;
import com.guojiang.guopicturebackend.model.vo.spaceuser.SpaceUserVO;
import com.guojiang.guopicturebackend.model.vo.user.MaskedUserVO;
import com.guojiang.guopicturebackend.service.SpaceService;
import com.guojiang.guopicturebackend.service.SpaceUserService;
import com.guojiang.guopicturebackend.mapper.SpaceUserMapper;
import com.guojiang.guopicturebackend.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 过江辉
 * @description 针对表【space_user(空间用户关联)】的数据库操作Service实现
 * @createDate 2025-01-31 11:30:31
 */
@Service
public class SpaceUserServiceImpl extends ServiceImpl<SpaceUserMapper, SpaceUser>
        implements SpaceUserService {

    @Resource
    @Lazy
    private SpaceService spaceService;

    @Resource
    private UserService userService;

    /**
     * 新增空间成员
     *
     * @param spaceUserAddRequest
     * @param loginUser
     * @return
     */
    @Override
    public long addSpaceUser(SpaceUserAddRequest spaceUserAddRequest, User loginUser) {
        // 1. 校验参数
        ThrowUtils.throwIf(spaceUserAddRequest == null, ErrorCode.PARAMS_ERROR, "spaceUserAddRequest 为空");
        SpaceUser spaceUser = new SpaceUser();
        BeanUtils.copyProperties(spaceUserAddRequest, spaceUser);
        // 默认新增用户都是
        spaceUser.setSpaceRole("viewer");
        // 校验基础参数
        validSpaceUser(spaceUser, true);
        // 校验业务参数
        Long spaceId = spaceUser.getSpaceId();
        Space space = spaceService.getById(spaceId);
        ThrowUtils.throwIf(SpaceTypeEnum.TEAM.getValue() != space.getSpaceType(), ErrorCode.OPERATION_ERROR, "非团队空间不能加入新成员");
        // 2. 校验权限
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR, "请先登录");
        // 当前登录用户，也就是操作人，必须在这个空间是管理员或创建人的身份
        Long operateUserId = loginUser.getId();
        SpaceUserQueryRequest spaceUserQueryRequest = new SpaceUserQueryRequest();
        spaceUserQueryRequest.setUserId(operateUserId);
        spaceUserQueryRequest.setSpaceId(spaceId);
        SpaceUser operationUserData = this.getOne(this.getQueryWrapper(spaceUserQueryRequest));
        ThrowUtils.throwIf(!SpaceRoleEnum.ADMIN.getValue().equals(operationUserData.getSpaceRole())
                        || !loginUser.getId().equals(space.getUserId())
                , ErrorCode.OPERATION_ERROR, "无权限");
        // 3. 插入数据库
        boolean saveResult = this.save(spaceUser);
        ThrowUtils.throwIf(!saveResult, ErrorCode.OPERATION_ERROR, "系统错误，请稍候重试");
        return spaceUser.getId();
    }

    /**
     * 校验空间成员
     *
     * @param spaceUser
     */
    @Override
    public void validSpaceUser(SpaceUser spaceUser, boolean add) {
        ThrowUtils.throwIf(spaceUser == null, ErrorCode.PARAMS_ERROR, "spaceUser 参数为空");
        // 取值等待校验
        Long spaceId = spaceUser.getSpaceId();
        Long userId = spaceUser.getUserId();
        if (add) {
            // 创建空间时，spaceId、userId不能为空
            ThrowUtils.throwIf(ObjUtil.hasEmpty(spaceId, userId), ErrorCode.PARAMS_ERROR, "请求参数不能为空");
            // 要操作的空间、用户均要存在
            User user = userService.getById(userId);
            ThrowUtils.throwIf(user == null, ErrorCode.PARAMS_ERROR, "要操作的用户不存在");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR, "要操作的空间不存在");
        }
        // 校验空间权限是否存在
        String spaceRole = spaceUser.getSpaceRole();
        ThrowUtils.throwIf(spaceRole == null, ErrorCode.PARAMS_ERROR, "权限配置不能为空");
        SpaceRoleEnum spaceRoleEnum = SpaceRoleEnum.getEnumByValue(spaceRole);
        ThrowUtils.throwIf(spaceRoleEnum == null, ErrorCode.PARAMS_ERROR, "权限配置非法");
    }

    /**
     * 获取空间成员封装类
     *
     * @param spaceUser
     * @param request
     * @return
     */
    @Override
    public SpaceUserVO getSpaceUserVO(SpaceUser spaceUser, HttpServletRequest request) {
        SpaceUserVO spaceUserVO = SpaceUser.objToVo(spaceUser);
        // 关联查询空间封装类信息
        Long spaceId = spaceUser.getSpaceId();
        Long userId = spaceUser.getUserId();
        if (spaceId != null && spaceId > 0) {
            Space space = spaceService.getById(spaceId);
            SpaceVO spaceVO = spaceService.getSpaceVO(space, request);
            spaceUserVO.setSpace(spaceVO);
        }
        // 关联查询用户封装类信息
        if (userId != null && userId > 0) {
            User user = userService.getById(userId);
            MaskedUserVO maskedUserVO = userService.getMaskedUserVO(user);
            spaceUserVO.setUser(maskedUserVO);
        }
        return spaceUserVO;
    }

    /**
     * 空间成员封装类列表（数量不会太多，不需要分页，获取列表即可）
     *
     * @param SpaceUserList
     * @return
     */
    @Override
    public List<SpaceUserVO> getSpaceUserVOList(List<SpaceUser> SpaceUserList) {
        if (CollUtil.isEmpty(SpaceUserList)) {
            return new ArrayList<>();
        }
        // 对象列表 => 封装对象列表  
        List<SpaceUserVO> spaceUserVOList = SpaceUserList.stream().map(SpaceUser::objToVo).collect(Collectors.toList());
        // 1. 关联查询用户封装类信息  
        Set<Long> userIdSet = SpaceUserList.stream().map(SpaceUser::getUserId).collect(Collectors.toSet());
        Set<Long> spaceIdSet = SpaceUserList.stream().map(SpaceUser::getSpaceId).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));
        Map<Long, List<Space>> spaceIdSpaceListMap = spaceService.listByIds(spaceIdSet).stream()
                .collect(Collectors.groupingBy(Space::getId));
        // 2. 填充信息  
        spaceUserVOList.forEach(spaceUserVO -> {
            Long userId = spaceUserVO.getUserId();
            Long spaceId = spaceUserVO.getSpaceId();
            // 填充用户封装类信息
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            spaceUserVO.setUser(userService.getMaskedUserVO(user));
            // 填充空间封装类信息
            Space space = null;
            if (spaceIdSpaceListMap.containsKey(spaceId)) {
                space = spaceIdSpaceListMap.get(spaceId).get(0);
            }
            spaceUserVO.setSpace(Space.objToVo(space));
        });
        return spaceUserVOList;
    }

    /**
     * 获取空间成员查询对象
     *
     * @param spaceUserQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<SpaceUser> getQueryWrapper(SpaceUserQueryRequest spaceUserQueryRequest) {
        QueryWrapper<SpaceUser> queryWrapper = new QueryWrapper<>();
        if (spaceUserQueryRequest == null) {
            return queryWrapper;
        }
        // 取值填充查询对象
        Long id = spaceUserQueryRequest.getId();
        Long spaceId = spaceUserQueryRequest.getSpaceId();
        Long userId = spaceUserQueryRequest.getUserId();
        String spaceRole = spaceUserQueryRequest.getSpaceRole();
        queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotEmpty(spaceId), "spaceId", spaceId);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjUtil.isNotEmpty(spaceRole), "spaceRole", spaceRole);
        return queryWrapper;
    }
}




